﻿using System;
using System.Collections.Generic;
using System.Threading;
using SmartContentModule.Helpers;
using SmartContentModule.VersionManagement;

namespace SmartContentModule.CssModel
{
    internal class CssFileInfoRefreshWorker
    {
        private static CssFileInfoRefreshWorker instance = null;
        private Thread thread;
        private int refreshIntervalInMilliSeconds = 10000;//default 10 mins

        /// <summary>
        /// Get lazy-loaded singleton instance
        /// </summary>
        public static CssFileInfoRefreshWorker Instance
        {
            get
            {
                if (instance == null)
                    instance = new CssFileInfoRefreshWorker();

                return instance;
            }
        }

        /// <summary>
        /// Initialize method starts refresher thread. Refresher thread regularly updates versions.
        /// This method used to call immediately in composition root (Global.asax)
        /// </summary>
        /// <param name="refreshIntervalInSeconds"></param>
        public void Initialize(int refreshIntervalInSeconds)
        {
            if (refreshIntervalInSeconds > 0)
                refreshIntervalInMilliSeconds = refreshIntervalInSeconds * 1000;

            StartRefresh();
        }

        private void StartRefresh()
        {
            ExceptionHelper.HandleWarning("Thread > CssFileInfoRefreshWorker starting thread...");
            StopRefresh();
            thread = new Thread(new ThreadStart(RefreshDependencies));
            thread.Start();
        }

        private void StopRefresh()
        {
            if (thread == null)
                return;

            if (!thread.IsAlive)
            {
                thread = null;
            }
            else
            {
                try
                {
                    thread.Abort();
                }
                catch (Exception ex)
                {
                    ExceptionHelper.HandleError("Thread > Could not abort CssFileInfoRefreshWorker thread.", ex);
                }
            }
        }

        private void RefreshDependencies()
        {
            while (true)
            {
                Thread.Sleep(refreshIntervalInMilliSeconds);

                try
                {
                    KeyValuePair<string, CssFileInfo>[] entryList = CssFileVersion.GetFileInfoList();
                    if (entryList == null || entryList.Length == 0)
                        continue;

                    foreach (KeyValuePair<string, CssFileInfo> pair in entryList)
                    {
                        string latestVersion = pair.Value.GetVersion();
                        //get current hash value, compare it in version table
                        List<string> versionList = CssFileVersion.GetVersionsUsingFileInfoUrl(pair.Value.ContentUrl);
                        if (versionList.Contains(latestVersion))
                            continue;

                        /* new version, 
                         * first update fileinfo so it refresh own temp file
                         * then, add new version to version table
                         * */
                        pair.Value.Update();
                        CssFileVersion.AddVersion(latestVersion, pair.Key);
                    }

                }
                catch (ThreadAbortException tex)
                {
                    ExceptionHelper.HandleWarning("Thread > CssFileInfoRefreshWorker aborted !");
                }
                catch (Exception ex)
                {
                    ExceptionHelper.HandleError("Thread > CssFileInfoRefreshWorker failed !", ex);
                }
            }
        }

        /// <summary>
        /// Stops refresher thread on dispose
        /// </summary>
        public void Dispose()
        {
            StopRefresh();
        }
    }
}
